package com.yfp.client.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.github.pagehelper.util.StringUtil;
import com.yfp.client.annotation.AnonymousAccess;
import com.yfp.client.config.WxMaConfiguration;
import com.yfp.client.config.WxPayProperties;
import com.yfp.client.domain.Client;
import com.yfp.client.domain.Machine;
import com.yfp.client.domain.MarCouponDirectional;
import com.yfp.client.domain.vo.LoginVo;
import com.yfp.client.generator.TokenGenerator;
import com.yfp.client.mapper.MachineMapper;
import com.yfp.client.service.ClientCouponService;
import com.yfp.client.service.ClientService;
import com.yfp.client.service.MarCouponDirectionalService;
import com.yfp.client.util.*;
import com.yfp.common.core.exception.GlobalException;
import com.yfp.common.core.exception.ServiceException;
import com.yfp.common.core.utils.StringUtils;
import com.yfp.common.redis.service.RedisService;
import com.yfp.client.util.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Description: 小程序微信登录
 *
 * @CreateDate: 2024/5/15 16:13
 * @UpdateUser:
 * @UpdateDate: 2024/5/15 16:13
 * @UpdateRemark: 暂无修改
 * @Version: 1.0
 */
@RestController
@RequestMapping("/client/login")
@Tag(name = "小程序登录模块")
@Slf4j
public class LoginController {

    @Autowired
    private RedisService redisService;
    @Autowired
    private ClientService clientService;
    @Autowired
    private AliyunSmsConf aliyunSmsConf;
    @Autowired
    private WxPayProperties wxPayProperties;
    @Autowired
    private MarCouponDirectionalService marCouponDirectionalService;
    @Autowired
    private ClientCouponService clientCouponService;
    @Autowired
    private MachineMapper machineMapper;

    @PostMapping("")
    @AnonymousAccess
    public Response login(@RequestBody LoginVo loginVo) {
        log.info("登录参数:{}",loginVo);
        final WxMaService wxService = WxMaConfiguration.getMaService(wxPayProperties.getConfigs().get(0).getAppId());
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(loginVo.getWeChatCode());
            log.info("session:{}", session);
            // 查找是否绑定
            Client client = clientService.getByOpenId(session.getOpenid());

            Map<String, Object> resultMap = new HashMap<>();
            if (null == client || StringUtils.isBlank(client.getMobile())) {
                resultMap.put("sessionKey", session.getSessionKey());
                resultMap.put("openId", session.getOpenid());
                resultMap.put("unionId", session.getUnionid());
                return Response.result(ResponseEnum.NOT_BIND, resultMap);
            }
            if (null != client.getStatus() && client.getStatus() == 0) {
                return Response.result(ResponseEnum.DISABLED);
            }

            if (StringUtils.isEmpty(client.getUnionId())) {
                client.setUnionId(session.getUnionid());
            }
            client.setCityName(loginVo.getCityName());
            clientService.edit(client);
            String token = TokenGenerator.createToken(client);
            redisService.setCacheObject(MessageFormat.format(RedisKey.LOGIN, client.getId()), client, 1L, TimeUnit.HOURS);
            resultMap.put("accessToken", token);
            resultMap.put("client", client);
            return Response.success(resultMap);
        } catch (Exception e) {
            e.printStackTrace();
            throw new GlobalException("获取openId失败");
        }
    }


    @Operation(summary = "授权手机号码登录")
    @PostMapping("/authMobile")
    @AnonymousAccess
    public Response authMobile(@RequestBody LoginVo loginVo) throws WxErrorException {
        log.info("注册参数:{}",loginVo);
        final WxMaService wxService = WxMaConfiguration.getMaService(wxPayProperties.getConfigs().get(0).getAppId());
        WxMaPhoneNumberInfo wxMaPhoneNumberInfo = wxService.getUserService().getPhoneNoInfo(loginVo.getWeChatCode());

        //  查询openId是否绑定其他手机号码
        Client byOpenId = clientService.getByOpenId(loginVo.getOpenId());


        Client client = clientService.findByMobile(wxMaPhoneNumberInfo.getPhoneNumber());
        if (null != client) {
            clientService.clearMobile(client.getId());
        }

        if (null == byOpenId) {
            byOpenId = new Client();
            String stringRandom = SmsSendUtil.getStringRandom(4);
            byOpenId.setOpenId(loginVo.getOpenId());
            byOpenId.setUnionId(loginVo.getUnionId());
            byOpenId.setMobile(wxMaPhoneNumberInfo.getPhoneNumber());
            byOpenId.setNickName("yfp_" + stringRandom);
            byOpenId.setInvitationClientId(loginVo.getInvitationClientId());
            // 状态默认启用

            byOpenId.setStatus(1);
            byOpenId.setEnterprise(loginVo.getEnterprise());
            byOpenId.setCityName(loginVo.getCityName());

            // 点位标签
            if (!StringUtil.isEmpty(loginVo.getMachineId())) {
                Machine machine = machineMapper.getById(loginVo.getMachineId());
                byOpenId.setPositionId(machine.getPositionId());
            }
            if (!StringUtil.isEmpty(loginVo.getInvitationClientId())) {
                // 邀请人信息
                Client cl = clientService.getById(loginVo.getInvitationClientId());
                byOpenId.setPositionId(cl.getPositionId());
            }
            clientService.add(byOpenId);
            // TODO 调用发放定向券
            List<MarCouponDirectional> marCouponDirectionals = marCouponDirectionalService.findByMobile(byOpenId.getMobile());
            for (MarCouponDirectional marCouponDirectional : marCouponDirectionals) {
                log.info("定向券：{}, clientId:{}", marCouponDirectional.getMarCouponId(), byOpenId.getId());
                ResponseEnum responseEnum = clientCouponService.verifyCoupon(marCouponDirectional.getMarCouponId(), byOpenId.getId(), null, null, null, null);
                log.info("发放结果：{}", responseEnum.getCode());
                marCouponDirectionalService.editStatus(marCouponDirectional.getId(), responseEnum.getCode().equals(ResponseEnum.OPERATOR_SUCCESS.getCode()) ? 3 : 4);
            }
        } else {
            byOpenId.setMobile(wxMaPhoneNumberInfo.getPhoneNumber());
//            client.setUnionId(loginVo.getUnionId());
            byOpenId.setCityName(loginVo.getCityName());
            clientService.edit(byOpenId);
        }
        if (null != byOpenId.getStatus() && byOpenId.getStatus() == 0) {
            return Response.result(ResponseEnum.DISABLED);
        }

        String token = TokenGenerator.createToken(byOpenId);
        redisService.setCacheObject(MessageFormat.format(RedisKey.LOGIN, byOpenId.getId()), client, 1L, TimeUnit.HOURS);

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("accessToken", token);
        resultMap.put("client", byOpenId);
        return Response.success(resultMap);
    }

    @Operation(summary = "获取手机验证码")
    @GetMapping("/captcha")
    @AnonymousAccess
    public Response captcha(@RequestParam("mobile") String mobile) {
        // 生成验证码
        String code = aliyunSmsConf.getSendCode();
        boolean result = true;
        if (aliyunSmsConf.getSend()) {
            code = SmsSendUtil.getVerifyNumber();
            result = SmsSendUtil.send(mobile, code, aliyunSmsConf);
        }
        log.info("获取手机验证码,手机号：{},验证码：{}", mobile, code);
        if (result) {
            redisService.setCacheObject(MessageFormat.format(RedisKey.LOGINVERIFYNUMBER, mobile), code, 5L, TimeUnit.MINUTES);
            return Response.success();
        } else {
            throw new ServiceException("验证码发送失败，请稍后再试");
        }
    }

    @Operation(summary = "手机号码登录")
    @PostMapping("/mobileCaptcha")
    @AnonymousAccess
    public Response mobileCaptcha(HttpServletRequest request, @RequestBody LoginVo loginVo) {
        log.info("手机号登录参数:{}",loginVo);
        String redisCode = redisService.getCacheObject(MessageFormat.format(RedisKey.LOGINVERIFYNUMBER, loginVo.getMobile()));
        if (StringUtils.isEmpty(redisCode)) {
            return Response.result(ResponseEnum.ANEW_CODE);
        } else if (!redisCode.equals(loginVo.getCaptchaCode())) {
            return Response.result(ResponseEnum.CODE_ERROR);
        }

        //  查询openId是否绑定其他手机号码
        Client client = clientService.findByMobile(loginVo.getMobile());
        if (null != client) {
            clientService.clearMobile(client.getId());
        }

        Client byOpenId = clientService.getByOpenId(loginVo.getOpenId());
        if (null == byOpenId) {
            String stringRandom = SmsSendUtil.getStringRandom(4);
            byOpenId = new Client();
            byOpenId.setOpenId(loginVo.getOpenId());
            byOpenId.setUnionId(loginVo.getUnionId());
            byOpenId.setMobile(loginVo.getMobile());
            byOpenId.setInvitationClientId(loginVo.getInvitationClientId());
            byOpenId.setNickName("yfp_" + stringRandom);
            // 状态默认启用
            byOpenId.setStatus(1);
            byOpenId.setEnterprise(loginVo.getEnterprise());
            byOpenId.setCityName(loginVo.getCityName());
            // 点位标签
            if (!StringUtil.isEmpty(loginVo.getMachineId())) {
                Machine machine = machineMapper.selectById(loginVo.getMachineId());
                byOpenId.setPositionId(machine.getPositionId());
            }
            if (!StringUtil.isEmpty(loginVo.getInvitationClientId())) {
                // 邀请人信息
                Client cl = clientService.getById(loginVo.getInvitationClientId());
                byOpenId.setPositionId(cl.getPositionId());
            }
            clientService.add(byOpenId);
            // TODO 调用发放定向券
            List<MarCouponDirectional> marCouponDirectionals = marCouponDirectionalService.findByMobile(byOpenId.getMobile());
            for (MarCouponDirectional marCouponDirectional : marCouponDirectionals) {
                ResponseEnum responseEnum = clientCouponService.verifyCoupon(marCouponDirectional.getMarCouponId(), byOpenId.getId(), null, null, null, null);
                marCouponDirectionalService.editStatus(marCouponDirectional.getId(), responseEnum.getCode().equals(ResponseEnum.OPERATOR_SUCCESS.getCode()) ? 3 : 4);
            }
        } else {
            byOpenId.setMobile(loginVo.getMobile());
//            byOpenId.setUnionId(loginVo.getUnionId());
            byOpenId.setCityName(loginVo.getCityName());
            clientService.edit(byOpenId);
        }
        String token = TokenGenerator.createToken(byOpenId);
        redisService.setCacheObject(MessageFormat.format(RedisKey.LOGIN, byOpenId.getId()), byOpenId, 1L, TimeUnit.HOURS);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("accessToken", token);
        resultMap.put("client", byOpenId);
        return Response.success(resultMap);
    }

    @Operation(summary = "退出接口")
    @PostMapping("logout")
    @AnonymousAccess
    public Response logout(HttpServletRequest request) {
        String userId = SecurityUtils.getClientId();
        // 清除redis缓存
        redisService.deleteObject(MessageFormat.format(RedisKey.LOGIN, userId));
        return Response.success();
    }
}